//#########################################################################
//                              WackiEngie
//           Copyright (c) 2014 Marc Wacker. All rights reserved.
//#########################################################################

#pragma once

#include "WeShader.h"

namespace WackiEngine
{

	//-----------------------------------------------------------------------------
	//! STL vector type for WEGLShader pointers
	typedef Vector<Shader*> VShader;

	//typedef unordered_map<const char*, int, hash<const char*>, eqstr> WELocMap;
	typedef Map<String, int> LocMap;


	class ShaderProg
	{
	private:
		uint32			_programObjectGL;	//!< OpenGL shader program object
		bool			_isLinked;			//!< Flag if program is linked
		VShader			_shaderList;		//!< Vector of all shader objects
		LocMap 			_uniformLocHash;	//!< Hashmap for all uniform locations
		LocMap 			_attribLocHash;		//!< Hashmap for all attribute locations
		String			_name;				//!< name of an object

	public:
		ShaderProg(const String& vertShaderFile = 0, const String& fragShaderFile = 0);
		~ShaderProg();			 

		void			addShader			(Shader *shader);			
		void			init				(); //!< create, attach & link shaders
		char*			getLinkerLog		(); //!< get linker messages
		
		virtual void	beginShader			() { beginUse(); }  //!< starter for derived classes
		virtual void	endShader			() { endUse(); }
		
		void			beginUse			();  //!< begin using shader
		void			endUse				();
		void			useProgram			();
				
		//Getters
		uint32			programObjectGL		() { return _programObjectGL; }
		
		//Variable location getters
		int			getUniformLocation	(const char *name);
		int			getAttribLocation	(const char *name);	  

		//Send unform variables to program
		int			uniform1f			(const char *name, float v0);
		int			uniform2f			(const char *name, float v0, float v1); 
		int			uniform3f			(const char *name, float v0, float v1, float v2);
		int			uniform4f			(const char *name, float v0, float v1, float v2, float v3);

		int			uniform1i			(const char *name, int v0);
		int			uniform2i			(const char *name, int v0, int v1);
		int			uniform3i			(const char *name, int v0, int v1, int v2);
		int			uniform4i			(const char *name, int v0, int v1, int v2, int v3);

		int			uniform1fv			(const char *name, int count, const float* value);
		int			uniform2fv			(const char *name, int count, const float* value);
		int			uniform3fv			(const char *name, int count, const float* value);
		int			uniform4fv			(const char *name, int count, const float* value);

		int			uniform1iv			(const char *name, int count, const int* value);
		int			uniform2iv			(const char *name, int count, const int* value);
		int			uniform3iv			(const char *name, int count, const int* value);
		int			uniform4iv			(const char *name, GLsizei count, const int* value);

		int			uniformMatrix2fv	(const char *name, int count, const float* value, GLboolean transpose=false);
		int			uniformMatrix3fv	(const char *name, int count, const float* value, GLboolean transpose=false);
		int			uniformMatrix4fv	(const char *name, int count, const float* value, GLboolean transpose=false); 
		// statics
		static String	defaultPath;		//!< default path for GLSE programs
	};

}
